/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.compomics.spectral.utilities.examples;

import com.compomics.spectral.utilities.filtering.wavelet.daubechies.DaubechiesWaveletFilter;
import com.compomics.util.experiment.massspectrometry.Spectrum;
import com.compomics.util.experiment.massspectrometry.SpectrumFactory;
import java.awt.BorderLayout;
import java.awt.Color;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.SpinnerNumberModel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import uk.ac.ebi.jmzml.xml.io.MzMLUnmarshallerException;

/**
 *
 * @author Kenneth
 */
public class DaubechiesFilter extends javax.swing.JFrame {

    private ArrayList<String> spectrumTitles;
    private int maxIndex;
    private SpectrumFactory factory;
    private Spectrum currentSpectrum;
    private double[] unfilteredIntensities;
    private double[] mzValues;
    private DaubechiesWaveletFilter daubechiesFilter;
    private double[] filteredIntensities;
    private SpinnerNumberModel spectrumSpinnerModel;
    private ArrayList<Integer> framesizeList;
    private Color[] colors = new Color[]{Color.BLACK, Color.GREEN, Color.PINK, Color.YELLOW, Color.BLUE, Color.orange, Color.pink, Color.magenta, Color.WHITE};
    private ChartPanel chartPanel;
    private int spectrumNumber;
    private XYSeriesCollection dataset;
    private JFreeChart chart;
    private XYPlot plot;
    private XYLineAndShapeRenderer renderer;
    private double[] daubechiesIntensities;

    /**
     * Creates new form DaubechiesFilter
     */
    public DaubechiesFilter() {
        this.setLayout(new java.awt.BorderLayout());
        this.framesizeList = new ArrayList<Integer>();
        initComponents();
        chartHolder.setLayout(new java.awt.BorderLayout());
    }

    public static void main(String args[]) {
        DaubechiesFilter filter = new DaubechiesFilter();
        filter.setVisible(true);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        chartHolder = new javax.swing.JPanel();
        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        rdbFrameSize5 = new javax.swing.JRadioButton();
        rdbFrameSize4 = new javax.swing.JRadioButton();
        rdbFrameSize3 = new javax.swing.JRadioButton();
        rdbFrameSize2 = new javax.swing.JRadioButton();
        rdbFrameSize1 = new javax.swing.JRadioButton();
        rdbFrameSize = new javax.swing.JRadioButton();
        jLabel1 = new javax.swing.JLabel();
        spectrumSpinner = new javax.swing.JSpinner();
        jLabel2 = new javax.swing.JLabel();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        chartHolder.setBackground(new java.awt.Color(255, 255, 255));
        chartHolder.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        javax.swing.GroupLayout chartHolderLayout = new javax.swing.GroupLayout(chartHolder);
        chartHolder.setLayout(chartHolderLayout);
        chartHolderLayout.setHorizontalGroup(
            chartHolderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 673, Short.MAX_VALUE)
        );
        chartHolderLayout.setVerticalGroup(
            chartHolderLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 315, Short.MAX_VALUE)
        );

        jButton1.setText("reload");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        rdbFrameSize5.setText("500");
        rdbFrameSize5.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rdbFrameSize5ActionPerformed(evt);
            }
        });

        rdbFrameSize4.setText("100");
        rdbFrameSize4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rdbFrameSize4ActionPerformed(evt);
            }
        });

        rdbFrameSize3.setText("50");
        rdbFrameSize3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rdbFrameSize3ActionPerformed(evt);
            }
        });

        rdbFrameSize2.setText("20");
        rdbFrameSize2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rdbFrameSize2ActionPerformed(evt);
            }
        });

        rdbFrameSize1.setText("10");
        rdbFrameSize1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rdbFrameSize1ActionPerformed(evt);
            }
        });

        rdbFrameSize.setSelected(true);
        rdbFrameSize.setText("5");
        rdbFrameSize.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rdbFrameSizeActionPerformed(evt);
            }
        });

        jLabel1.setText("Framesize");

        jLabel2.setText("Spectrum");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel1)
                            .addComponent(rdbFrameSize4)
                            .addComponent(rdbFrameSize5)
                            .addComponent(rdbFrameSize1)
                            .addComponent(rdbFrameSize)
                            .addComponent(rdbFrameSize2)
                            .addComponent(rdbFrameSize3)
                            .addComponent(spectrumSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel2))
                        .addGap(0, 11, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(spectrumSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
                .addComponent(jLabel1)
                .addGap(18, 18, 18)
                .addComponent(rdbFrameSize)
                .addGap(2, 2, 2)
                .addComponent(rdbFrameSize1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(rdbFrameSize2)
                .addGap(3, 3, 3)
                .addComponent(rdbFrameSize3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(rdbFrameSize4)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(rdbFrameSize5)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jButton1)
                .addGap(34, 34, 34))
        );

        jMenu1.setText("File");

        jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.ALT_MASK));
        jMenuItem1.setText("Load Spectrum...");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem1);

        jMenuBar1.add(jMenu1);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(chartHolder, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(chartHolder, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setVisible(true);
        fileChooser.showOpenDialog(this);
        File selectedMGF = fileChooser.getSelectedFile();
        if (selectedMGF != null) {
            try {
                importMGF(selectedMGF);
                framesizeList.add(currentSpectrum.getMzValuesAsArray().length);
            } catch (IOException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            } catch (IllegalArgumentException ex) {
                ex.printStackTrace();
            }
        }
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void rdbFrameSize1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdbFrameSize1ActionPerformed
    }//GEN-LAST:event_rdbFrameSize1ActionPerformed

    private void rdbFrameSize4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdbFrameSize4ActionPerformed
    }//GEN-LAST:event_rdbFrameSize4ActionPerformed

    private void rdbFrameSize5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdbFrameSize5ActionPerformed
    }//GEN-LAST:event_rdbFrameSize5ActionPerformed

    private void rdbFrameSizeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdbFrameSizeActionPerformed
    }//GEN-LAST:event_rdbFrameSizeActionPerformed

    private void rdbFrameSize2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdbFrameSize2ActionPerformed
    }//GEN-LAST:event_rdbFrameSize2ActionPerformed

    private void rdbFrameSize3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdbFrameSize3ActionPerformed
    }//GEN-LAST:event_rdbFrameSize3ActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        try {
            spectrumNumber = (int) spectrumSpinner.getValue();
            visualizeSpectrum(spectrumNumber);
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        } catch (MzMLUnmarshallerException ex) {
            ex.printStackTrace();
        }
    }//GEN-LAST:event_jButton1ActionPerformed
    /**
     * @param args the command line arguments
     */
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel chartHolder;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JRadioButton rdbFrameSize;
    private javax.swing.JRadioButton rdbFrameSize1;
    private javax.swing.JRadioButton rdbFrameSize2;
    private javax.swing.JRadioButton rdbFrameSize3;
    private javax.swing.JRadioButton rdbFrameSize4;
    private javax.swing.JRadioButton rdbFrameSize5;
    private javax.swing.JSpinner spectrumSpinner;
    // End of variables declaration//GEN-END:variables

    private void importMGF(File selectedMGF) throws IOException, FileNotFoundException, ClassNotFoundException {
        if (factory == null) {
            factory = SpectrumFactory.getInstance();
        } else {
            factory.clearFactory();
        }
        factory.addSpectra(selectedMGF);
        spectrumTitles = factory.getSpectrumTitles(selectedMGF.getName());
        maxIndex = factory.getNSpectra();
        spectrumSpinnerModel = new SpinnerNumberModel(0, 0, maxIndex, 1);
        spectrumSpinner.setModel(spectrumSpinnerModel);
        spectrumSpinner.validate();
        spectrumSpinner.repaint();
        fillList();
        try {
            visualizeSpectrum(spectrumNumber);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(DaubechiesFilter.class.getName()).log(Level.SEVERE, null, ex);
        } catch (MzMLUnmarshallerException ex) {
            Logger.getLogger(DaubechiesFilter.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void fillList() {
        framesizeList.clear();
        //fill list with framesize
        if (rdbFrameSize.isSelected()) {
            framesizeList.add(5);
        }
        if (rdbFrameSize1.isSelected()) {
            framesizeList.add(10);
        }
        if (rdbFrameSize2.isSelected()) {
            framesizeList.add(20);
        }
        if (rdbFrameSize3.isSelected()) {
            framesizeList.add(50);
        }
        if (rdbFrameSize4.isSelected()) {
            framesizeList.add(100);
        }
        if (rdbFrameSize5.isSelected()) {
            framesizeList.add(500);
        }
    }

    private void visualizeSpectrum(int spectrumKey) throws IOException, IllegalArgumentException, MzMLUnmarshallerException {
        currentSpectrum = factory.getSpectrum(factory.getMgfFileNames().get(0), spectrumTitles.get(spectrumKey));
        framesizeList.clear();
        fillList();
        if (currentSpectrum != null && !framesizeList.contains(new Integer(currentSpectrum.getMzValuesAsArray().length))) {
            framesizeList.add(currentSpectrum.getMzValuesAsArray().length);
        }
        mzValues = currentSpectrum.getMzValuesAsArray();
        unfilteredIntensities = currentSpectrum.getIntensityValuesAsArray();
        if (dataset == null) {
            dataset = new XYSeriesCollection();
        }
        if (renderer == null) {
            renderer = new XYLineAndShapeRenderer();
        }
        dataset.removeAllSeries();
        //MAKE THE DATASET
        filteredIntensities = new double[unfilteredIntensities.length];
        System.arraycopy(unfilteredIntensities, 0, filteredIntensities, 0, unfilteredIntensities.length);
        daubechiesFilter = new DaubechiesWaveletFilter(mzValues, filteredIntensities);
        daubechiesIntensities = daubechiesFilter.transform();
        XYSeries daubechiesseries = new XYSeries("Daubechies ");
        for (int i = 0; i < daubechiesIntensities.length; i++) {
            daubechiesseries.add(mzValues[i], daubechiesIntensities[i]);
        }
        renderer.setShapesVisible(false);
        renderer.setSeriesPaint(0, Color.RED);
        renderer.setSeriesLinesVisible(0, true);
        renderer.setSeriesShapesVisible(0, false);
        for (int anInt : framesizeList) {
            filteredIntensities = daubechiesFilter.filterFramedData(anInt);
            XYSeries series = new XYSeries("Framesize " + anInt);
            for (int i = 0; i < filteredIntensities.length; i++) {
                series.add(mzValues[i], filteredIntensities[i]);
            }

            if (framesizeList.indexOf(new Integer(anInt+1)) >= 0) {
                renderer.setSeriesPaint(framesizeList.indexOf(new Integer(anInt + 1)), colors[framesizeList.indexOf(new Integer(anInt+1))]);
                renderer.setSeriesShapesVisible(framesizeList.indexOf(new Integer(anInt + 1)), false);
                renderer.setSeriesLinesVisible(framesizeList.indexOf(new Integer(anInt + 1)), true);
            }
            dataset.addSeries(series);
            dataset.addSeries(daubechiesseries);
        }
        if (chart == null) {
            chart = ChartFactory.createXYLineChart(
                    "Spectrum filtration", // chart title
                    "m/z", // x axis label
                    "Intensity", // y axis label
                    dataset, // data
                    PlotOrientation.VERTICAL,
                    true, // include legend
                    true, // tooltips
                    false // urls
                    );
            // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
            chart.setBackgroundPaint(Color.white);

            //        final StandardLegend legend = (StandardLegend) chart.getLegend();
            //      legend.setDisplaySeriesShapes(true);

            // get a reference to the plot for further customisation...
            plot = chart.getXYPlot();
            plot.setBackgroundPaint(Color.lightGray);
            //    plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0));
            plot.setDomainGridlinePaint(Color.white);
            plot.setRangeGridlinePaint(Color.white);

            plot.setRenderer(renderer);
            // change the auto tick unit selection to integer units only...
            final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
            rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
            // OPTIONAL CUSTOMISATION COMPLETED.
            chartPanel = new ChartPanel(chart);
            // chartPanel.setPreferredSize(new java.awt.Dimension(chartHolder.getWidth(), chartHolder.getHeight()));
            chartHolder.add(chartPanel, BorderLayout.CENTER);
        }
        chartPanel.revalidate();
        chartPanel.repaint();
        chartHolder.revalidate();
        chartHolder.repaint();
        chartHolder.setVisible(true);
    }
}
